/** GeometricSeriesVisual.java
 *
 *	Lil Applet for visualizing geometric series.
 *	Author: Ralph Gootee (c) 2007
 *	GPL License 
 **/

import java.awt.*;
import java.applet.*;
import java.awt.event.*;

import javax.swing.*;
import javax.swing.event.*;
import javax.swing.border.Border;


public class GeometricSeriesVisual extends JApplet 
	implements ChangeListener, ActionListener, ListSelectionListener
{
	private GeoVisual g;
	private JSlider nSlider,aSlider,rSlider;

	private JLabel nOut,aOut,rOut,convOut;

	private JButton colorButton;

	private JComboBox shapeCombo;

	private JList pointList;

	//------------------------------------------------------------------------------
	public void init()  {
		//setBackground(Color.magenta);
		
		GridBagLayout gridbag = new GridBagLayout();
       	GridBagConstraints c = new GridBagConstraints();
		Container cp = getContentPane();	

		cp.setLayout(gridbag); 

		// Create the Geomertic Visual
		g = new GeoVisual();
		
		// Sames size for all sliders
		Dimension outDim = new Dimension(30,20);
		Dimension sDim = new Dimension(200,20);

		int wxLabel = 1;
		int wxSlider = 10;

		// Geometric image
		GeoImage img = new GeoImage();
		c.insets = new Insets(5,5,5,5);
		c.anchor = GridBagConstraints.CENTER;
		c.gridx=0;c.gridy=0;c.gridwidth=1;c.gridheight=3;
		c.weightx=1;c.weighty=.5;
		cp.add(img,c);
		
		// N
		JLabel nLabel = new JLabel("N:");
		c.insets = new Insets(0,0,0,0);
		nLabel.setPreferredSize(outDim);
		c.anchor = GridBagConstraints.EAST;
		c.fill = GridBagConstraints.NONE;	
		c.gridx=1;c.gridy=0;c.gridwidth=1;c.gridheight=1;
		c.weightx=wxLabel;
		cp.add(nLabel,c);
		
		nSlider = new JSlider(1,200,g.getN());
		nSlider.addChangeListener(this);
		nSlider.setMinimumSize(sDim);
		c.fill = GridBagConstraints.BOTH;
		c.gridx=2;c.gridy=0;
		c.weightx=wxSlider;
		cp.add(nSlider,c);
	
		nOut = new JLabel(new Double(g.getN()).toString());
		nOut.setMinimumSize(outDim);
		nOut.setPreferredSize(outDim);
		c.gridx=3;c.gridy=0;
		c.weightx=.5;c.weighty=.5;
		cp.add(nOut,c);
	
		//A
		JLabel aLabel = new JLabel("a:");
		aLabel.setPreferredSize(outDim);
		c.fill = GridBagConstraints.NONE;
		c.anchor = GridBagConstraints.EAST;
		c.gridx=1;c.gridy=1;
		c.weightx=wxLabel;
		cp.add(aLabel,c);

		aSlider = new JSlider(1,200,aInv(g.getA()));
		aSlider.addChangeListener(this);
		c.fill = GridBagConstraints.BOTH;
		c.anchor = GridBagConstraints.WEST;
		c.gridx=2;c.gridy=1;
		c.weightx=wxSlider;
		cp.add(aSlider,c);
	
		aOut = new JLabel(new Double(g.getA()).toString());
		aOut.setMinimumSize(outDim);
		aOut.setPreferredSize(outDim);
		c.gridx=3;c.gridy=1;
		c.weightx=wxLabel;
		cp.add(aOut,c);

		// R
		JLabel rLabel = new JLabel("r:");
		rLabel.setPreferredSize(outDim);
		c.fill = GridBagConstraints.NONE;
		c.anchor = GridBagConstraints.EAST;
		c.gridx=1;c.gridy=2;
		c.weightx=wxLabel;
		cp.add(rLabel,c);

		rSlider = new JSlider(1,100,rInv(g.getR()));
		c.fill = GridBagConstraints.BOTH;
		rSlider.addChangeListener(this);
		c.weightx=wxSlider;
		c.gridx=2;c.gridy=2;
		cp.add(rSlider,c);
		
		rOut = new JLabel(new Double(g.getA()).toString());
		rOut.setMinimumSize(outDim);
		rOut.setPreferredSize(outDim);
		c.weightx=wxLabel;
		c.gridx=3;c.gridy=2;
		cp.add(rOut,c);

		// Visual
		c.gridx=0;c.gridy=3;c.gridwidth=4;
		c.weightx=1;c.weighty=1;
		c.insets = new Insets(5,10,5,5);
		c.fill=GridBagConstraints.BOTH;
		cp.add(g,c);

		// Color Button
		colorButton = new JButton("color...");
		colorButton.addActionListener(this);
		c.anchor = GridBagConstraints.CENTER;
		c.gridx=0;c.gridy=4;c.gridwidth=1;c.gridheight=1;	
		c.fill=GridBagConstraints.NONE;
		cp.add(colorButton,c);
		
		// Shape Combo Box
		String [] shapes = {"Ellipse","Square"};
		shapeCombo = new JComboBox(shapes);
		shapeCombo.addActionListener(this);
		c.gridx=1;c.gridy=4;
		cp.add(shapeCombo,c);

		// List	
		pointList = new JList();
		pointList.setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION);
		pointList.addListSelectionListener(this);
		
		JScrollPane listScroller = new JScrollPane(pointList);
		listScroller.setPreferredSize(new Dimension(200, 80));
		c.insets = new Insets(5,20,5,5);
		c.gridx=4; c.gridy=3;c.gridheight=1;c.gridwidth=2;
		c.fill=GridBagConstraints.BOTH;
		cp.add(listScroller,c);

		JLabel convLabel = new JLabel("Converges: ");

		c.gridx=4;c.gridy=4;c.gridheight=1;c.gridwidth=1;
		cp.add(convLabel,c);

		convOut = new JLabel("x");
		c.gridx=5;c.gridy=4;
		cp.add(convOut,c);

		// Update the list
		updateList();
		g.repaint();
	}
 	
	//------------------------------------------------------------------------------
	public void actionPerformed(ActionEvent e) {
		if(e.getSource() == colorButton){
			Color c = JColorChooser.showDialog(this,"Pick a Color",g.getBaseColor());
			if(c != null) g.setBaseColor(c);
		}else if(e.getSource() == shapeCombo){
			g.setShape(shapeCombo.getSelectedIndex());
		}
	}
	
	//------------------------------------------------------------------------------
	public void stateChanged(ChangeEvent e) {
    	JSlider source = (JSlider)e.getSource();
    	
		if (!source.getValueIsAdjusting()){
			if(source == nSlider){
        		int n = (int)source.getValue();
				nOut.setText(new Integer(n).toString());
				g.setN(n);	
			}else if(source == aSlider){
				double a = aTrans(source.getValue());
				g.setA(a);
				aOut.setText(new Double(a).toString());
			
			}else if(source == rSlider){
				double r = (source.getValue());
				g.setR(r);
				rOut.setText(new Double(r).toString());
			}
			updateList();
		}
	}	

	//------------------------------------------------------------------------------
	public void valueChanged(ListSelectionEvent listSelectionEvent) {
        
		boolean adjust = listSelectionEvent.getValueIsAdjusting();
        
		if (!adjust) {
        	JList list = (JList) listSelectionEvent.getSource();
    		int s = list.getSelectedIndex();
			g.setSelectedIndex(s);
		}
    }
	
	//------------------------------------------------------------------------------
	public void updateList(){

		double [] p = g.getPoints();
		Double [] d = new Double[p.length];

		for(int i=0;i<p.length;i++) d[i] = new Double(p[i]);

		pointList.setListData(d);
	
		convOut.setText(new Double(g.getConv()).toString() );
	}

	//------------------------------------------------------------------------------
	private double aTrans(double i){ return (i - 100)/50;}

	//------------------------------------------------------------------------------
	private int aInv(double a){ return (int)Math.floor((a* 50) + 100.0);}
	
	//------------------------------------------------------------------------------
	private int rInv(double r){ return (int)Math.floor(r);}


	//------------------------------------------------------------------------------
	private class GeoImage extends JPanel{
		Image img;
	
		//------------------------------------------------------------------------------
		public GeoImage(){
			Dimension d = new Dimension(100,85);
			setPreferredSize(d);
			setMinimumSize(d);

			Border blackline = BorderFactory.createLineBorder(Color.black);
			setBorder(blackline);

			try{
				img = getImage(getDocumentBase(), "geometric_form.gif"); 
				
			}catch(Exception e){
				System.out.println("[Error] Could not Load Image!\n" + e);
			}
		
		}
		
		//------------------------------------------------------------------------------
		public void paint(Graphics g){
			//g.setColor(Color.white);	
			//g.fillRect(0,0,getSize().width,85);
		
			if(img!=null){
				g.drawImage(img,20,5,this);
				g.dispose();
			}
		}
	}

}
